﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Reflection;
using Vbyte.SharpOrm.Config;
using System.Data.Common;
using Vbyte.Extension;
using Vbyte.DataSource.Cache;

namespace Vbyte.SharpOrm
{
    public partial class TableEntry 
	{
        /// <summary>
        /// 同步实体对象的子对象（数组属性）
        /// </summary>
        /// <param name="cmdType">数据库操作类型</param>
        /// <param name="PropertyPredicate">对该属性是否应用操作的判断</param>
        /// <returns>如果操作成功则返回为字符0，失败则为异常消息和堆栈信息。</returns>
        public string SynChild(SQLRowCommandType cmdType, Func<string, object[], bool> PropertyPredicate)
        {
            string result = "0";
            Type instanceType = this.GetType();
            PropertyInfo[] Properties = GenericCache<PropertyInfo[]>.Get(instanceType.FullName, () => instanceType.GetProperties());
            foreach (PropertyInfo pi in Properties)
            {
                if (!pi.PropertyType.IsArray)
                {
                    continue;
                }
                else
                {
                    object[] childObjects = pi.GetGetMethod().Invoke(this, null) as object[];
                    if (PropertyPredicate != null && !PropertyPredicate(pi.Name, childObjects)) continue;

                    try
                    {
                        Type childInstanceType = pi.PropertyType.GetElementType();
                        if (!OrmHelper.HasAttribute(pi, typeof(ChildTableAttribute), true) ||
                            !childInstanceType.IsSubclassOf(typeof(TableEntry)))
                        {
                            continue;
                        }
                        else
                        {
                            //添加、更新、删除时子对象不为空
                            ChildTableAttribute cAttr = OrmHelper.GetMemberInfoCustomAttributes<ChildTableAttribute>(pi, true)[0];
                            if (cAttr.DependencyProperties == null || cAttr.DependencyProperties.Length == 0)
                            {
                                cAttr.DependencyProperties = new string[] { pi.Name };
                            }

                            string parentPropName, childPropName;
                            string[] parentChildPropName = new string[1];
                            //Console.WriteLine(cAttr.DependencyProperties.ToJSON());

                            if ((childObjects == null || childObjects.Length == 0) && cmdType == SQLRowCommandType.Select)
                            {
                                #region 子对象为空项(绑定子对象数据)
                                TableEntry childEntry = System.Activator.CreateInstance(childInstanceType) as TableEntry;
                                #region 设置从父级对象关联的值
                                foreach (string pKey in cAttr.DependencyProperties)
                                {
                                    parentChildPropName = pKey.Split(':');
                                    parentPropName = parentChildPropName[0];
                                    childPropName = (parentChildPropName.Length > 1) ? parentChildPropName[1] : parentPropName;

                                    ReflectCache.SetProperty(childInstanceType, childEntry, childInstanceType.GetProperty(childPropName),
                                        ReflectCache.GetProperty(instanceType, this, instanceType.GetProperty(parentPropName)));
                                }
                                #endregion

                                pi.SetValue(this, typeof(OrmHelper).GetMethod("GetDataList", BindingFlags.Public | BindingFlags.Static, null, CallingConventions.Any, new Type[] { typeof(TableEntry) }, null)
                                    .MakeGenericMethod(childInstanceType)
                                    .Invoke(null, new object[] { childEntry }),
                                    null);

                                //Console.WriteLine(pi.GetGetMethod().Invoke(this, null).ToJSON());
                                #endregion
                            }
                            else
                            {
                                TableEntry[] childEntries = Array.ConvertAll<object, TableEntry>(childObjects, d => (TableEntry)d);
                                //Array.CreateInstance(pi.PropertyType.GetElementType(), 0);
                                #region 子级对象的同步
                                using (DbConnection conn = childEntries[0].GetDbConnection())
                                {
                                    conn.Open();
                                    for (int i = 0, j = childEntries.Length; i < j; i++)
                                    {
                                        TableEntry entry = childEntries[i];

                                        #region 设置从父级对象关联的值
                                        foreach (string pKey in cAttr.DependencyProperties)
                                        {
                                            parentChildPropName = pKey.Split(':');
                                            parentPropName = parentChildPropName[0];
                                            childPropName = (parentChildPropName.Length > 1) ? parentChildPropName[1] : parentPropName;

                                            ReflectCache.SetProperty(childInstanceType, entry, childInstanceType.GetProperty(childPropName),
                                                ReflectCache.GetProperty(instanceType, this, instanceType.GetProperty(parentPropName)));
                                        }
                                        #endregion

                                        //删除存在的子级数据 Delete
                                        if (cmdType == SQLRowCommandType.Delete)
                                        {
                                            entry.Delete(conn);
                                        }
                                        else
                                        {
                                            //判定是否存在 存在则更新 Insert Update
                                            if (cmdType == SQLRowCommandType.Update || entry.GetTotalRecord(conn) > 0)
                                            {
                                                //Console.WriteLine(entry.GeneratorDbCommand(SQLRowCommandType.Update).CommandText); 
                                                entry.Update(conn);
                                            }
                                            else
                                            {
                                                entry.Insert(conn);
                                            }

                                        }

                                    }
                                    conn.Close();
                                }
                                #endregion
                            }

                        }
                    }
                    catch (Exception exp)
                    {
                        exp = exp.GetTriggerException();
                        result = exp.Message + Environment.NewLine
                            + exp.StackTrace;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 同步实体对象的子对象（数组属性）
        /// </summary>
        /// <param name="cmdType">>数据库操作类型</param>
        /// <returns>如果操作成功则返回为字符0，失败则为异常消息和堆栈信息。</returns>
        public string SynChild(SQLRowCommandType cmdType)
        {
            return SynChild(cmdType, null);
        }
    }
}
